﻿using System;
using System.Collections.Generic;
using System.Workflow.ComponentModel;
using CrmContrib.Workflow.Activities.Domain;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.Workflow;
using Microsoft.Crm.Sdk.Query;
using Microsoft.Crm.SdkTypeProxy;
using System.Text;

namespace CrmContrib.Workflow.Activities.Contracts
{
    [CrmWorkflowActivity("Get contract lines summary", "CrmContrib \\ Contracts")]
    public partial class GetContractLinesSummary : Activity
    {
        [CrmOutput("Output")]
        public string Output
        {
            get { return (string)GetValue(OutputProperty); }
            set { SetValue(OutputProperty, value); }
        }

        public static readonly DependencyProperty OutputProperty = DependencyProperty.Register("Output", typeof(string), typeof(GetContractLinesSummary));

        private readonly List<Contract> _contracts = new List<Contract>();
        private readonly Dictionary<Guid, string> _contractTemplateUnits = new Dictionary<Guid, string>();

        protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
        {
            var contextService = executionContext.GetService<IContextService>();
            var workflowContext = contextService.Context;
            var crmService = workflowContext.CreateCrmService();

            var contractQuery = new QueryExpression { EntityName = EntityName.contract.ToString(), ColumnSet = new AllColumns() };
            var contractResult = (RetrieveMultipleResponse)crmService.Execute(new RetrieveMultipleRequest { Query = contractQuery, ReturnDynamicEntities = true });

            var contractTemplateQuery = new QueryExpression { EntityName = EntityName.contracttemplate.ToString(), ColumnSet = new AllColumns() };
            var contractTempateResult = (RetrieveMultipleResponse)crmService.Execute(new RetrieveMultipleRequest { Query = contractTemplateQuery, ReturnDynamicEntities = true });

            var contractLineQuery = new QueryExpression { EntityName = EntityName.contractdetail.ToString(), ColumnSet = new AllColumns() };
            var contractLineResult = (RetrieveMultipleResponse)crmService.Execute(new RetrieveMultipleRequest { Query = contractLineQuery, ReturnDynamicEntities = true });

            foreach (DynamicEntity entity in contractTempateResult.BusinessEntityCollection.BusinessEntities)
            {
                var contractTemplateId = entity.Properties.Contains("contracttemplateid")
                                     ? ((Key)entity.Properties["contracttemplateid"]).Value
                                     : Guid.Empty;
                var contractTemplateUnit = entity.Properties.Contains("allotmenttypecode")
                                     ? ((Picklist)entity.Properties["allotmenttypecode"]).name
                                     : "";
                _contractTemplateUnits.Add(contractTemplateId, contractTemplateUnit);
            }

            foreach (DynamicEntity entity in contractResult.BusinessEntityCollection.BusinessEntities)
            {
                var contractState = entity.Properties.Contains("statecode")
                                     ? entity.Properties["statecode"].ToString()
                                     : "";
                if (!contractState.Equals("Active")) { continue; }

                var contractId = entity.Properties.Contains("contractid")
                                     ? ((Key)entity.Properties["contractid"]).Value
                                     : Guid.Empty;

                var contractName = entity.Properties.Contains("title")
                                     ? entity.Properties["title"].ToString()
                                     : "";

                var contractTemplateId = entity.Properties.Contains("contracttemplateid")
                                     ? ((Lookup)entity.Properties["contracttemplateid"]).Value
                                    : Guid.Empty;

                var contractTemplateUnit = "minutes";
                if (_contractTemplateUnits.ContainsKey(contractTemplateId))
                {
                    contractTemplateUnit = _contractTemplateUnits[contractTemplateId];
                    switch(contractTemplateUnit)
                    {
                        case "Number of Cases" :
                            contractTemplateUnit = "cases";
                            break;
                        case "Time":
                            contractTemplateUnit = "minutes";
                            break;
                        case "Coverage Dates":
                            contractTemplateUnit = "dates";
                            break;
                    }
                }

                _contracts.Add(new Contract
                                     {
                                       Id = contractId,
                                       Title = contractName,
                                       ContractTemplateUnit = contractTemplateUnit
                                     });
            }

            foreach (DynamicEntity entity in contractLineResult.BusinessEntityCollection.BusinessEntities)
            {
                var contractId = entity.Properties.Contains("contractid")
                                         ? ((Lookup)entity.Properties["contractid"]).Value
                                         : Guid.Empty;
                if (!_contracts.Exists(c => c.Id == contractId)){ continue; }

                var contractItem = _contracts.Find(c => c.Id == contractId);

                var contractLineId = entity.Properties.Contains("contractdetailid")
                                         ? ((Key)entity.Properties["contractdetailid"]).Value
                                         : Guid.Empty;

                var contractLineTitle = entity.Properties.Contains("title")
                                         ? entity.Properties["title"].ToString()
                                         : "";

                var contractLineAllotmentsUsed = entity.Properties.Contains("allotmentsused")
                                         ? ((CrmNumber)entity.Properties["allotmentsused"]).Value
                                         : 0;

                var contractLineTotalAllotments = entity.Properties.Contains("totalallotments")
                                         ? ((CrmNumber)entity.Properties["totalallotments"]).Value
                                         : 0;

                if (contractItem.ContractLines == null) { contractItem.ContractLines = new List<ContractLine>(); }
                contractItem.ContractLines.Add(new ContractLine
                                         {
                                            Id = contractLineId,
                                            Title = contractLineTitle,
                                            AllotmentsUsed = contractLineAllotmentsUsed,
                                            TotalAllotments = contractLineTotalAllotments,
                                            AllotmentUnit = contractItem.ContractTemplateUnit
                                         });
            }

            var builder = new StringBuilder();
            foreach (var contract in _contracts)
            {
                //if (contract.ContractLines.Count == 0) { continue; } //only print the contract title if there are contract lines
                builder.AppendLine(String.Format("<strong>{0}</strong>", contract.Title));

                foreach (var contractLine in contract.ContractLines)
                {
                    builder.AppendLine(contractLine.ContractLineSummary);
                }
                builder.AppendLine();
            }

            this.Output = builder.ToString();
            return base.Execute(executionContext);
        }
    }
}
